package de.reondo.jos;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;

import org.jgrapht.DirectedGraph;
import org.jgrapht.alg.FloydWarshallShortestPaths;

public class DependencyListPrinter<V, E extends IWitness<?>> {
    
    private DirectedGraph<V, E> graph;
    private IGraphStyler<V, E> styler; 
    
    public DependencyListPrinter(DirectedGraph<V, E> graph, IGraphStyler<V, E> styler) {
        super();
        this.graph = graph;
        this.styler = styler;
    }

    public void printDependencyList(String filename) throws IOException {
        PrintWriter out = new PrintWriter(filename, "UTF-8");
        out.println("Dependency list generated " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").format(new Date()));
        // unusable, as it ignores directedness: ConnectivityInspector<V, E> ci = new ConnectivityInspector<V, E>(graph);
        FloydWarshallShortestPaths<V, E> sp = new FloydWarshallShortestPaths<V, E>(graph);
        for (V v : graph.vertexSet()) {
            HashMap<V, String> direct = new HashMap<V, String>();
            HashMap<V, String> trans = new HashMap<V, String>();
            out.println(styler.getVertexLabel(v));
            for (E e : graph.edgesOf(v)) {
                if (graph.getEdgeSource(e).equals(v)) {
                    V t = graph.getEdgeTarget(e);
                    direct.put(t, e.getWitness().toString());
                }
            }
            printDeps("Direct dependencies:", direct, out, true);
            for (V t : graph.vertexSet()) {
                if (! t.equals(v) && ! direct.containsKey(t) && sp.shortestDistance(v, t) != Double.POSITIVE_INFINITY) {
                    trans.put(t, "");
                } 
            }
            printDeps("Transitive dependencies:", trans, out, false);
        }
        out.close();
    }

    private void printDeps(String heading, HashMap<V, String> direct, PrintWriter out, boolean printValues) throws IOException {
        ArrayList<V> all = new ArrayList<V>(direct.keySet());
        Collections.sort(all, new Comparator<V>() {
            @Override
            public int compare(V o1, V o2) {
                return styler.getVertexLabel(o1).compareTo(styler.getVertexLabel(o2));
            }
            
        });
        if (all.size() > 0) {
            out.println("  " + heading);
            for (V v : all) {
                if (printValues) 
                    out.println("    " + styler.getVertexLabel(v) + " ["+direct.get(v)+"]");
                else
                    out.println("    " + styler.getVertexLabel(v));
            }
        }
    }

}
